﻿using System;
using System.Reflection;
using System.Threading.Tasks;
using Project.DTO;
using Project.IBLL;
using Project.IDAL;
using Project.Models;

namespace Project.BLL
{
    /// <summary>
    /// IBLL 层中的基类接口
    /// </summary>
    public class BaseManager<TDModel, TModel, TIClass> : IBaseManager<TDModel>
    where TDModel : BaseEntityDto, new()
    where TModel : BaseEntity, new()
    where TIClass : IBaseServices<TModel>
    {
#pragma warning disable 693
        /// <summary>
        /// 反射实现两个类的对象之间相同属性的值的复制
        /// 适用于初始化新实体
        /// </summary>
        /// <typeparam name="TModel"></typeparam>
        /// <typeparam name="TDModel"></typeparam>
        /// <param name="dto">数据源实体</param>
        /// <returns>返回的新实体</returns>
        private TModel Mapper<TModel, TDModel>(TDModel dto)
        {
            TModel d = Activator.CreateInstance<TModel>(); //构造新实例
            var types = dto.GetType();//获得类型  
            var typed = typeof(TModel);
            foreach (PropertyInfo sp in types.GetProperties())//获得类型的属性字段  
            {
                foreach (PropertyInfo dp in typed.GetProperties())
                {
                    if (dp.Name == sp.Name && dp.PropertyType == sp.PropertyType && dp.Name != "Error" && dp.Name != "Item")//判断属性名是否相同  
                    {
                        dp.SetValue(d, sp.GetValue(dto, null), null);//获得s对象属性的值复制给d对象的属性  
                    }
                }
            }
            return d;
        }
        /// <summary>
        /// 反射实现两个类的对象之间相同属性的值的复制
        /// 适用于没有新建实体之间
        /// </summary>
        /// <typeparam name="TDModel"></typeparam>
        /// <typeparam name="TModel"></typeparam>
        /// <param name="model"></param>
        /// <param name="dto">数据源实体</param>
        /// <returns></returns>
        private TModel MapperToModel<TModel, TDModel>(TModel model, TDModel dto)
        {
            var types = dto.GetType();//获得类型  
            var typed = typeof(TModel);
            foreach (PropertyInfo sp in types.GetProperties())//获得类型的属性字段  
            {
                foreach (PropertyInfo dp in typed.GetProperties())
                {
                    if (dp.Name == sp.Name && dp.PropertyType == sp.PropertyType && dp.Name != "Error" && dp.Name != "Item")//判断属性名是否相同  
                    {
                        dp.SetValue(model, sp.GetValue(dto, null), null);//获得s对象属性的值复制给d对象的属性  
                    }
                }
            }
            return model;
        }

#pragma warning restore 693
        public BaseManager(TIClass services)
        {
            this._port = services;
        }

        private readonly TIClass _port;
        public async Task _Add(TDModel dto)
        {
            await _port.InsertAsync(Mapper<TModel, TDModel>(dto));
        }

        public async Task _Remove(TDModel dto)
        {
            await _port.DeleteAsync(Mapper<TModel, TDModel>(dto));
        }

        public async Task _Remove(long id)
        {
            await _port.DeleteByIdAsync(id);
        }

        public async Task _Edit(TDModel dto)
        {
            await _port.UpdateAsync(Mapper<TModel, TDModel>(dto));
        }
    }
}
